/**
 * 组件通用部分
 */
function scCommon(){
    /**
     * 创建元素
     * @param {*} tagName 
     * @param {*} clazz
     * @returns 
     */
    var crEle = function(tagName, clazz){
        tagName = tagName ? tagName : "div";
        
        var element = document.createElement(tagName);
        if(clazz){
            if(clazz.indexOf(",") > -1){
                let arr = clazz.split(",");
                for(var i in arr){
                    element.classList.add(arr[i].trim());
                }
            }else{
                element.classList.add(clazz);
            }
        }

        if(tagName.toLowerCase() == "input" && (element.type == "text" || !element.type)){
            element.setAttribute("autocomplete", "off");
        }

        return element;
    }

    /**
     * 插入脚本功能
     * @param {*} ref 
     * @param {*} data
     * @param {*} clazz
     */
    var insertScript = function(ref, data, clazz){
        var row = crEle("div", clazz.row);
        var label = crEle("label");
        var script = crEle("input");
        var btn = crEle("button", "sc-dialog-button");

        label.innerText = "脚本内容：";
        
        script.type = "text";
        script.placeholder = "显示脚本内容";
        script.setAttribute("name", "script");
        script.setAttribute("readonly", true);

        if(data && data.script != undefined){
            script.value = data.script;
        }else{
            script.value = "";
        }

        btn.innerText = "...";

        row.appendChild(label);
        row.appendChild(script);
        row.appendChild(btn);

        ref.node.appendChild(row);

        btn.addEventListener("click", (e)=>{
            let offset = getElementOffset(e.target);
            
            offset.left += e.target.clientWidth;
            offset.top += e.target.clientHeight;

            let param = {
                //是否是子对话框
                childDialog: true,
                //是否显示帮助按钮
                help: true,
                //标题
                label: "编辑脚本", 
                //显示组件
                component: new scScript({
                    //数据
                    data: {
                        script: ref.component.getData().script
                    }
                })
            };

            let dialog = new scDialog();
            let listener = null;

            dialog.setLayout(offset);
            dialog.createView(param, listener);
            dialog.submit = function(d){
                script.value = d;
            }
        });
    }

    /**
     * 获取元素在文档中的偏移量
     * @param {*} element 父元素
     * @returns 
     */
    var getElementOffset = function(element) {
        var left = element.offsetLeft;
        var top = element.offsetTop;

        var current = element.offsetParent;

        while (current) {
            left += current.offsetLeft;
            top += current.offsetTop;

            current = current.offsetParent;
        }

        return {
            left: left,
            top: top
        };
    }

    /**
     * 获取设置后的数据
     * @param box
     * @param filter
     */
    var getData = async function(box, filter){
        var nodes = box.querySelectorAll("input[name],select,textarea,img[name]");
        var data = {};
        var node = null;
        
        for(let i = 0; i < nodes.length; i++){
            node = nodes[i];
            if(node.type == "radio"){
                if(node.checked){
                    data[node.name] = node.value;
                }
            }else if(node.type == "checkbox"){
                if(node.value === "true" || node.value === "false"){
                    data[node.name] = node.checked;
                }else{
                    if(!data[node.name]){
                        data[node.name] = [];
                    }
                    data[node.name].push(node.value);
                }
            }else if(node.type == "file" && node.files.length > 0){
                data[node.name] = await new Promise((resolve)=>{
                    var reader = new FileReader();
                    reader.readAsDataURL(node.files[0]);
                    reader.onload = function(e){ 
                        resolve(e.target.result);
                    }
                });
            }else if(node.tagName.toLowerCase() == "img"){
                data[node.name] = node.src;
            }else{
                if(node.name.indexOf(".") > -1){
                    let names = node.name.split(".");
                    let dt = data;
                    for(let j = 0; j < names.length; j++){
                        if(j == names.length - 1){
                            dt[names[j]] = node.value;
                        }else{
                            if(!dt[names[j]]){
                                dt[names[j]] = {};
                            }
                            dt = dt[names[j]];
                        }
                    }
                }else{
                    data[node.name] = node.value;
                }
            }
        }

        if(filter){
            filter(data);
        }

        return data;
    }

    /**
     * 设置元素值
     * @param {*} node 
     * @param {*} data 
     * @param {*} name 
     * @param {*} defaultVal
     */
    var setValue = function(node, data, name, defaultVal){
        let val = getValue(data, name);
        if(val != null && val != ""){
            node.value = val;
        }else if(defaultVal != null){
            node.value = defaultVal;
        }
    }

    /**
     * 从数据中抽取值
     * @param {*} data 
     * @param {*} name 
     */
    var getValue = function(data, name){
        if(name.indexOf(".") > -1){
            let dt = data;
            let arr = name.split(".");
            for(let i = 0; i < arr.length; i++){
                dt = dt[arr[i]];
                if(dt === undefined || dt === null) return null;
            }
            return dt;
        }
        return data[name] != null ? data[name] : "";
    }

    /**
     * 绑定下拉框
     * @param {*} container 容器
     * @param {*} button 按钮
     * @param {*} component 组件
     * @param {*} param 组件参数
     */
    var bindDropdown = function(container, button, component, param){
        button.classList.add("sc-dialog-button");

        container.appendChild(button);
        container.classList.add("sc-common-container");

        var dropdownBox = crEle("div", "sc-dropdown-box");
        container.appendChild(dropdownBox);

        param.container = dropdownBox;

        var node = component.createView(param);
        node.style.zoom = 0.9;
        dropdownBox.appendChild(node);

        button.addEventListener("click", (e)=>{
            let node = e.target.classList.contains("sc-dialog-button") 
                ? e.target 
                : e.target.parentNode;
            let left = node.offsetLeft;
            let top = node.offsetTop + node.clientHeight + 5;

            if(dropdownBox.classList.contains("active")){
                dropdownBox.classList.remove("active");
            }else{
                dropdownBox.style.left = left + "px";
                dropdownBox.style.top = top + "px";
                dropdownBox.classList.add("active");
            }
        });

        return dropdownBox;
    }

    /**
     * 获取父元素
     * @param {*} tagName 指定tagName 
     */
    var getParentNode = function(node, tagName){
        for(let n = node; n != null; n = n.parentNode){
            if(n.tagName.toLowerCase() == tagName.toLowerCase()){
                return n;
            }
        }
        return null;
    }

    /**
     * 插入节点
     * @param {*} items 
     * @param {*} data
     * @param {*} wrap 
     * @param {*} rowClazz
     * @param {*} afterInsert
     */
    var insertNode = function(items, data, wrap, rowClazz, afterInsert){
        let row = null;
        let item = null;
        let label = null;

        for (let i in items) {
            item = items[i];
            row = crEle("div", rowClazz);

            label = crEle("label");
            label.innerText = item.label;

            row.appendChild(label);

            if(item.groups){
                for(let i in item.groups){
                    insertElement(item.groups[i], label, row, data, afterInsert);
                }
            }else{
                insertElement(item, label, row, data, afterInsert);
            }

            wrap.appendChild(row);
        }
    }

    /**
     * 插入元素
     * @param {*} item 
     * @param {*} label
     * @param {*} row 
     * @param {*} data 
     * @param {*} afterInsert 
     */
    var insertElement = function(item, label, row, data, afterInsert){
        let input = null;

        if (item.component) {
            input = eval("new " + item.component + "()");
            if (item.type == "component") {
                let param = {
                    ...item.param,
                }

                setValue(param, data, item.value 
                    ? item.value 
                    : item.param.name, 
                    item.param.value
                );

                row.appendChild(input.createView(param));
            }else if(item.type == "dropdown"){
                let btn = crEle("button");
                if(item.display == "color"){
                    let color = getValue(data, item.value);
                    let colorDiv = crEle("div", "sc-color-display");

                    colorDiv.style.backgroundColor = color;
                    
                    let hidden = crEle("input");
                    hidden.type = "hidden";
                    hidden.name = item.value;
                    
                    btn.appendChild(colorDiv);
                    btn.appendChild(hidden);

                    var dropdown = null;

                    let param = {
                        ...item.param, 
                        triggerListener: (color)=>{
                            colorDiv.style.backgroundColor = color;
                            hidden.value = color;
                            dropdown.classList.remove("active");
                        }
                    };
                    param[item.display] = color;

                    dropdown = bindDropdown(row, btn, input, param);
                }
            }
        } else if (item.type == "select") {
            input = crEle("select");
            input.name = item.value;
            
            let val = null;
            for (let i = 0; i < item.list.length; i++) {
                let op = crEle("option");
                op.value = item.list[i];
                op.innerText = op.value;
                input.appendChild(op);

                if(item.selectedIndex == i){
                    val = op.value;
                }
            }
            row.appendChild(input);
            setValue(input, data, input.name, val);
        } else if(item.type == "image"){
            input = crEle("img");
            input.name = item.value;

            row.appendChild(input);
        } else if(item.type == "div"){
            input = crEle("div");
            input.setAttribute("name", item.value);

            row.appendChild(input);
        } else{
            input = crEle("input");
            input.name = item.value;

            if(item.type == "file"){
                input.type = item.type;
                input.accept = item.accept;

                row.appendChild(input);
            }else if(item.type == "checkbox" || item.type == "radio"){
                let lab = crEle("label");
                lab.innerText = item.label;
                row.appendChild(lab);

                input.type = item.type;
                input.checked = item.checked === true;
                setValue(input, data, input.name, item.defaultVal);
                lab.prepend(input);

                row.appendChild(lab);
            }else{
                input.type = "text";
                input.placeholder = item.placeholder;
                setValue(input, data, input.name);

                row.appendChild(input);
            }
        }

        if(item.style){
            for(let i in item.style){
                input.style[i] = item.style[i];
            }
        }

        if(item.checkEnable){
            let checkbox = crEle("input");

            checkbox.type = "checkbox";
            checkbox.name = item.checkOption.name;
            checkbox.checked = item.checkOption.checked;
            checkbox.value = item.checkOption.checked;

            label.prepend(checkbox);

            if(afterInsert){
                afterInsert(checkbox, input, row);
            }
        }

        if(input && afterInsert){
            afterInsert(input);
        }
    }

    return {
        crEle: crEle,
        getData: getData,
        setValue: setValue,
        getValue: getValue,
        insertNode: insertNode,
        insertScript: insertScript,
        bindDropdown: bindDropdown,
        getParentNode: getParentNode
    }
}

/**
 * 创建实例
 * @returns 
 */
scCommon.instance = function(){
    return new scCommon();
}